'use strict';

Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.DownRefresh = exports.downState = exports.getTouchPoint = exports.calcAngle = undefined;

var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');

var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);

var _createClass2 = require('babel-runtime/helpers/createClass');

var _createClass3 = _interopRequireDefault(_createClass2);

var _extends2 = require('babel-runtime/helpers/extends');

var _extends3 = _interopRequireDefault(_extends2);

var _passiveEventListener = require('public/util/passiveEventListener');

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var calcAngle = exports.calcAngle = function calcAngle(point1, point2) {
    var x = Math.abs(point1.x - point2.x);
    var y = Math.abs(point1.y - point2.y);
    var z = Math.sqrt(x * x + y * y);
    return Math.asin(y / z) / Math.PI * 180;
};

var getTouchPoint = exports.getTouchPoint = function getTouchPoint(e) {
    return {
        x: e.touches[0].pageX,
        y: e.touches[0].pageY
    };
};
var downState = exports.downState = {
    end: 0,
    starting: 1,
    moving: 2
};
var _resetData = function _resetData() {
    var data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};

    return (0, _extends3.default)({
        state: downState.end,
        point: null,
        startPoint: null,
        lastPoint: null,
        diffStartY: 0,
        diffLastY: 0,
        height: 0 }, data);
};
var setConfig = function setConfig() {
    var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};

    return (0, _extends3.default)({
        minAngle: 45,
        onDown: function onDown() {},
        onDownEnd: function onDownEnd() {},
        onDownStart: function onDownStart() {},
        enableDown: function enableDown() {
            return true;
        }
    }, config);
};

var DownRefresh = exports.DownRefresh = function () {
    (0, _createClass3.default)(DownRefresh, [{
        key: 'resetData',
        value: function resetData(data) {
            this.data = _resetData(data);
        }
    }]);

    function DownRefresh(dom, config) {
        var _this = this;

        (0, _classCallCheck3.default)(this, DownRefresh);
        this.data = _resetData();

        this.touchStart = function (e) {
            if (!_this.isTop()) {
                return false;
            }
            var point = getTouchPoint(e);
            _this.resetData({
                startPoint: point,
                lastPoint: point,
                state: downState.starting
            });
            _this.bindMove();
        };

        this.touchMove = function (e) {
            var point = getTouchPoint(e);
            var data = _this.data;
            data.point = point;
            if (data.state !== downState.moving) {
                _this.initTouchMove(e, point);
            } else {
                _this._touchMove(e, point);
            }
            data.lastPoint = point;
        };

        this.touchEnd = function () {
            if (_this.data.state === downState.end) {
                return;
            }
            _this.cancelDown();
        };

        this.dom = dom;
        this.config = setConfig(config);
        this.bindEvents();
    }

    (0, _createClass3.default)(DownRefresh, [{
        key: 'isTop',
        value: function isTop() {
            return this.dom.scrollTop <= 1;
        }
    }, {
        key: 'isDown',
        value: function isDown(point) {
            return point.y - this.data.lastPoint.y > 0;
        }
    }, {
        key: 'initTouchMove',
        value: function initTouchMove(e, point) {
            var state = this.data.state;

            if (state !== downState.starting || !this.checkAngle(point) || !this.isDown(point) || !this.config.enableDown(this.data)) {
                this.data.state = downState.end;
                this.unbindMove();
                return false;
            }
            this.config.onDownStart(this.data);
            this.data.state = downState.moving;
            this._touchMove(e, point);
        }
    }, {
        key: '_touchMove',
        value: function _touchMove(e, point) {
            var _data = this.data,
                startPoint = _data.startPoint,
                lastPoint = _data.lastPoint;

            var diffStartY = point.y - startPoint.y;
            var diffLastY = point.y - lastPoint.y;

            var _calcDownHeight = this.calcDownHeight(diffStartY, diffLastY),
                height = _calcDownHeight.height;

            var data = this.data;
            data.diffStartY = diffStartY;
            data.diffLastY = diffLastY;
            data.height = height;
            data.diffLastY = diffLastY;

            this.config.onDown(this.data);
            (0, _passiveEventListener.preventDefault)(e);
        }
    }, {
        key: 'cancelDown',
        value: function cancelDown() {
            this.config.onDownEnd();
            this.resetData();
        }
    }, {
        key: 'calcDownHeight',
        value: function calcDownHeight(diffStartY, diffLastY) {
            var _config = this.config,
                outOffsetRate = _config.outOffsetRate,
                offset = _config.offset;

            var diffHeight = diffStartY >= offset ? diffLastY * outOffsetRate : diffLastY;
            return {
                height: diffStartY + diffHeight,
                diffHeight: diffHeight
            };
        }
    }, {
        key: 'checkAngle',
        value: function checkAngle(point) {
            var lastPoint = this.data.lastPoint;

            var angle = calcAngle(lastPoint, point);
            return angle > this.config.minAngle;
        }
    }, {
        key: 'bindMove',
        value: function bindMove() {
            this.dom.addEventListener('touchmove', this.touchMove);
        }
    }, {
        key: 'unbindMove',
        value: function unbindMove() {
            this.dom.removeEventListener('touchmove', this.touchMove);
        }
    }, {
        key: 'bindEvents',
        value: function bindEvents() {
            var dom = this.dom;
            this.unbindEvents();

            (0, _passiveEventListener.addEventListener)(dom, 'touchstart', this.touchStart);
            (0, _passiveEventListener.addEventListener)(dom, 'touchend', this.touchEnd);
            (0, _passiveEventListener.addEventListener)(dom, 'touchcancel', this.touchEnd);
        }
    }, {
        key: 'unbindEvents',
        value: function unbindEvents() {
            var dom = this.dom;
            (0, _passiveEventListener.removeEventListener)(dom, 'touchstart', this.touchStart);
            (0, _passiveEventListener.removeEventListener)(dom, 'touchend', this.touchEnd);
            (0, _passiveEventListener.removeEventListener)(dom, 'touchcancel', this.touchEnd);
        }
    }, {
        key: 'destroy',
        value: function destroy() {
            this.unbindMove();
            this.unbindEvents();
        }
    }]);
    return DownRefresh;
}();

exports.default = DownRefresh;